package cn.growthgate.fgo.handler;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authz.AuthorizationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.spring.FastJsonJsonView;

import cn.growthgate.fgo.common.Constants;
import cn.growthgate.fgo.entity.ExceptionLog;
import cn.growthgate.fgo.service.IExceptionLogService;
import cn.growthgate.fgo.util.AuthenticationUtils;
import cn.growthgate.fgo.util.RequestUtils;
import cn.growthgate.fgo.util.StringUtils;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
	
	@Autowired
	private IExceptionLogService exceptionLogService;
	
	@Override
	protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
			HttpStatus status, WebRequest request) {
		return super.handleExceptionInternal(ex, body, headers, status, request);
	}
	
	@ExceptionHandler(AuthorizationException.class)
	public ModelAndView authorizationException(HttpServletRequest request) throws IOException {
		if (AuthenticationUtils.isUser()) {
			// 已登录
			if (RequestUtils.isAjaxRequest(request)) {
				// ajax请求，返回异常信息
				ModelAndView mav = new ModelAndView(new FastJsonJsonView()).addObject("msg", "你没有访问的权限");
				mav.setStatus(HttpStatus.FORBIDDEN);
				return mav;
			} else {
				// 非ajax请求，响应403页面
				ModelAndView mav = new ModelAndView("/error/403");
				mav.setStatus(HttpStatus.FORBIDDEN);
				return mav;
			}
		} else {
			// 未登录
			//保存登录前的页面信息,只保存GET请求。其他请求不处理。
			if (HttpMethod.GET.matches(request.getMethod())) {
				if (request.getSession().getAttribute(Constants.SESSION_LOGIN_REQUEST_URL) == null) {
					String requestUrl = RequestUtils.getRequestUrl(request);
					if (StringUtils.isNotBlank(requestUrl)) {
						request.getSession().setAttribute(Constants.SESSION_LOGIN_REQUEST_URL, requestUrl);
					}
				}
			}
			ModelAndView mav = new ModelAndView("forward:" + AuthenticationUtils.DEFAULT_LOGIN_URL);
			mav.addObject("msg", "请先登录");
			mav.setStatus(HttpStatus.UNAUTHORIZED);
			return mav;
		}
	}
	
	@ExceptionHandler(Exception.class)
	public ModelAndView authorizationException(HttpServletRequest request, Exception e) {
		String stackTrace = null;
		try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw);) {
			e.printStackTrace(pw);
			stackTrace = sw.toString();
		} catch (IOException e1) {
		}
		// 记录日志
		ExceptionLog log = new ExceptionLog();
		log.setUserId(AuthenticationUtils.getLoginUserId());
		log.setHost(RequestUtils.getIp(request));
		log.setUri(request.getRequestURI());
		log.setParams(JSON.toJSONString(request.getParameterMap()));
		log.setName(e.getClass().getName());
		log.setStackTrace(stackTrace);
		exceptionLogService.insert(log);
		if (RequestUtils.isAjaxRequest(request)) {
			// ajax请求，返回异常信息
			return new ModelAndView(new FastJsonJsonView()).addObject("msg", e.getLocalizedMessage());
		} else {
			// 非ajax请求，响应500页面
			return new ModelAndView("error/500");
		}
	}
	
}
